/*
 *  SSCatalystAppController.m
 *  MESLib
 * 
 * Copyright 2003-2009 Starline Software Ltd
 * 
 * This file is part of MESLib.
 * 
 * MESLib is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * MESLib is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with MESLib. If not, see <http://www.gnu.org/licenses/>.
 */
//  Created by Tobias Haughton on Fri Jan 24 2003.
//SSCatalystAppController is primarily used to send messages to documents triggered by non standard
//application menu items


#import "SSCatalystAppController.h"
#import "SSCatalystDocument.h"

NSString *SSCatalystDocToolbarIdentifier = @"Catlyst Document Toolbar Identifier";
NSString *SSNewEBToolbarItemIdentifier = @"New EB Toolbar Item Identifier";
NSString *SSNewAlertCommentToolbarItemIdentifier = @"New alert comment Toolbar Item Identifier";
NSString *SSNewNoteCommentToolbarItemIdentifier = @"New note comment Toolbar Item Identifier";
NSString *SSNewQuestionCommentToolbarItemIdentifier = @"New question comment Toolbar Item Identifier";
NSString *SSSnapChartToTimesToolbarItemIdentifier = @"Snap Chart To Times Toolbar Item Identifier";
NSString *SSSnapTimesToChartToolbarItemIdentifier = @"Snap Times To Chart Toolbar Item Identifier";
NSString *SSDeleteSelectedToolbarItemIdentifier = @"Delete selected blocks Toolbar Item Identifier";
NSString *SSExportToolbarItemIdentifier = @"Export Toolbar Item Identifier";
NSString *SSInspectorToolbarItemIdentifier = @"Inspector Toolbar Item Identifier";
NSString *SSNeedsDiamondToolbarItemIdentifier = @"Needs Diamond Toolbar Item Identifier";
NSString *SSFilterToolbarItemIdentifier = @"SSFilterToolbarItemIdentifier";
NSString *SSZoomInToolbarItemIdentifier = @"SSZoomInToolbarItemIdentifier";
NSString *SSZoomOutToolbarItemIdentifier = @"SSZoomOutToolbarItemIdentifier";
NSString *SSSwitchViewTypeToolbarItemIdentifier = @"SSSwitchViewTypeToolbarItemIdentifier";
NSString *SSZoomOutOverlapToolbarItemIdentifier = @"SSZoomOutOverlapToolbarItemIdentifier";
NSString *SSZoomInOverlapToolbarItemIdentifier = @"SSZoomInOverlapToolbarItemIdentifier";


NSString *PrivateDragPboard = @"SSTableViewPrivatePBoardType";

NSString *SSDisplayEBSourceKey = @"SSDisplayEBSourceKey";
NSString *SSDisplayEBObjectKey = @"SSDisplayEBObjectKey";
NSString *SSDisplayEBLocationKey = @"SSDisplayEBLocationKey";
NSString *SSDisplayEBBeginDateKey = @"SSDisplayEBBeginDateKey";
NSString *SSDisplayEBEndDateKey = @"SSDisplayEBEndDateKey";
NSString *SSDisplayEBActorKey = @"SSDisplayEBActorKey";
NSString *SSDateDisplayKey = @"SSDateDisplayKey";
NSString *SSDisplayJumpMapKey = @"SSDisplayJumpMapKeyV2";
NSString *SSDisplayChartLegendKey = @"SSDisplayChartLegendKey";

NSString *SSEBTableActorColumnKey = @"SSEBTableActorColumnKey";
NSString *SSEBTableActionColumnKey = @"SSEBTableActionColumnKey";
NSString *SSEBTableObjectColumnKey = @"SSEBTableObjectColumnKey";
NSString *SSEBTableLocationColumnKey = @"SSEBTableLocationColumnKey";
NSString *SSEBTableSourceColumnKey = @"SSEBTableSourceColumnKey";
NSString *SSEBTableRemarkColumnKey = @"SSEBTableRemarkColumnKey";
NSString *SSEBTableBegindateColumnKey = @"SSEBTableBegindateColumnKey";
NSString *SSEBTableEnddateColumnKey = @"SSEBTableEnddateColumnKey";
NSString *SSEBTableBegintimeColumnKey = @"SSEBTableBegintimeColumnKey";
NSString *SSEBTableEndtimeColumnKey = @"SSEBTableEndtimeColumnKey";
NSString *SSEBTableXpositionColumnKey = @"SSEBTableXpositionColumnKey";
NSString *SSEBTableLabelColumnKey = @"SSEBTableLabelColumnKey";
NSString *SSEBTableDurationColumnKey = @"SSEBTableDurationColumnKey";


NSString *SSDiamondTableNumberColumnKey = @"SSDiamondTableNumberColumnKey";
NSString *SSDiamondTableOwnertypeColumnKey = @"SSDiamondTableOwnertypeColumnKey";
NSString *SSDiamondTableOwnerdescriptionColumnKey = @"SSDiamondTableOwnerdescriptionColumnKey";
NSString *SSDiamondTableAnalystColumnKey = @"SSDiamondTableAnalystColumnKey";
NSString *SSDiamondTableFileidColumnKey = @"SSDiamondTableFileidColumnKey";
NSString *SSDiamondTableDescriptionColumnKey = @"SSDiamondTableDescriptionColumnKey";
NSString *SSDiamondTableDiamondstateColumnKey = @"SSDiamondTableDiamondstateColumnKey";
NSString *SSDiamondTableUdvalue1ColumnKey = @"SSDiamondTableUdvalue1ColumnKey";
NSString *SSDiamondTableUdvalue2ColumnKey = @"SSDiamondTableUdvalue2ColumnKey";
NSString *SSDiamondTableUdvalue3ColumnKey = @"SSDiamondTableUdvalue3ColumnKey";
NSString *SSDiamondTableUdvalue4ColumnKey = @"SSDiamondTableUdvalue4ColumnKey";
NSString *SSDiamondTableUdvalue5ColumnKey = @"SSDiamondTableUdvalue5ColumnKey";
NSString *SSDiamondTableUdvalue6ColumnKey = @"SSDiamondTableUdvalue6ColumnKey";

NSString *SSDiamondOptionTableOptionColumnKey = @"SSDiamondOptionTableOptionColumnKey";
NSString *SSDiamondOptionTableUdvalue1ColumnKey = @"SSDiamondOptionTableUdvalue1ColumnKey";
NSString *SSDiamondOptionTableUdvalue2ColumnKey = @"SSDiamondOptionTableUdvalue2ColumnKey";
NSString *SSDiamondOptionTableUdvalue3ColumnKey = @"SSDiamondOptionTableUdvalue3ColumnKey";
NSString *SSDiamondOptionTableUdvalue4ColumnKey = @"SSDiamondOptionTableUdvalue4ColumnKey";
NSString *SSDiamondOptionTableUdvalue5ColumnKey = @"SSDiamondOptionTableUdvalue5ColumnKey";
NSString *SSDiamondOptionTableIndexColumnKey = @"SSDiamondOptionTableIndexColumnKey";

NSString *SSDiamondTradeoffTableUdvalue1ColumnKey = @"SSDiamondTradeoffTableUdvalue1ColumnKey";
NSString *SSDiamondTradeoffTableUdvalue2ColumnKey = @"SSDiamondTradeoffTableUdvalue2ColumnKey";
NSString *SSDiamondTradeoffTableUdvalue3ColumnKey = @"SSDiamondTradeoffTableUdvalue3ColumnKey";
NSString *SSDiamondTradeoffTableProColumnKey = @"SSDiamondTradeoffTableProColumnKey";
NSString *SSDiamondTradeoffTableConColumnKey = @"SSDiamondTradeoffTableConColumnKey";
NSString *SSDiamondTradeoffTableIndexColumnKey = @"SSDiamondTradeoffTableIndexColumnKey";

NSString *SSCommentTableCommentstringColumnKey = @"SSCommentTableCommentstringColumnKey";
NSString *SSCommentTableXpositionColumnKey = @"SSCommentTableXpositionColumnKey";
NSString *SSCommentTableYpositionColumnKey = @"SSCommentTableYpositionColumnKey";
NSString *SSCommentTableTypeColumnKey = @"SSCommentTableTypeColumnKey";

NSString *SSStartupOptionKey = @"SSStartupOptionKey";

NSString *SSLastSavedFileKey = @"SSLastSavedFileKey";

NSString *SSSaveBackupKey = @"SSSaveBackupKey";
NSString *SSSaveBackupFrequencyKey = @"SSSaveBackupFrequencyKey";

NSString *SSFirstRunKey = @"SSFirstRunKey";

NSString *SSDefaultWhiteLabelDesignationKey = @"SSDefaultWhiteLabelDesignationKey";
NSString *SSDefaultYellowLabelDesignationKey = @"SSDefaultYellowLabelDesignationKey";
NSString *SSDefaultGreenLabelDesignationKey = @"SSDefaultGreenLabelDesignationKey";
NSString *SSDefaultLightBlueLabelDesignationKey = @"SSDefaultLightBlueLabelDesignationKey";
NSString *SSDefaultBlueLabelDesignationKey = @"SSDefaultBlueLabelDesignationKey";
NSString *SSDefaultPurpleLabelDesignationKey = @"SSDefaultPurpleLabelDesignationKey";
NSString *SSDefaultOrangeLabelDesignationKey = @"SSDefaultOrangeLabelDesignationKey";
NSString *SSDefaultRedLabelDesignationKey = @"SSDefaultRedLabelDesignationKey";
NSString *SSDefaultTitleKey = @"SSDefaultTitleKey";
NSString *SSDefaultAuthorKey = @"SSDefaultAuthorKey";
NSString *SSDefaultDateKey = @"SSDefaultDateKey";

NSString *SSDefaultDiamondUDValue1Key = @"SSDefaultDiamondUDValue1Key";
NSString *SSDefaultDiamondUDValue2Key = @"SSDefaultDiamondUDValue2Key";
NSString *SSDefaultDiamondUDValue3Key = @"SSDefaultDiamondUDValue3Key";
NSString *SSDefaultDiamondUDValue4Key = @"SSDefaultDiamondUDValue4Key";
NSString *SSDefaultDiamondUDValue5Key = @"SSDefaultDiamondUDValue5Key";
NSString *SSDefaultDiamondUDValue6Key = @"SSDefaultDiamondUDValue6Key";

NSString *SSDefaultDiamondOptionUDValue1Key = @"SSDefaultDiamondOptionUDValue1Key";
NSString *SSDefaultDiamondOptionUDValue2Key = @"SSDefaultDiamondOptionUDValue2Key";
NSString *SSDefaultDiamondOptionUDValue3Key = @"SSDefaultDiamondOptionUDValue3Key";
NSString *SSDefaultDiamondOptionUDValue4Key = @"SSDefaultDiamondOptionUDValue4Key";
NSString *SSDefaultDiamondOptionUDValue5Key = @"SSDefaultDiamondOptionUDValue5Key";

NSString *SSDefaultDiamondTradeoffUDValue1Key = @"SSDefaultDiamondTradeoffUDValue1Key";
NSString *SSDefaultDiamondTradeoffUDValue2Key = @"SSDefaultDiamondTradeoffUDValue2Key";
NSString *SSDefaultDiamondTradeoffUDValue3Key = @"SSDefaultDiamondTradeoffUDValue3Key";

NSString *SSDisplayDupeWarningKey = @"SSDisplayDupeWarningKey";

NSString *SSDefaultProjectFolderKey = @"SSDefaultProjectFolderKey";

NSString *SSCatalystSerialNumberKey = @"SSCatalystSerialNumberKey";

NSString *SSDefaultPoisonWordListKey = @"SSDefaultPoisonWordListKey";

NSString *SSCatalystChartObjectType = @"Catalyst chart object format";

@implementation SSCatalystAppController

+ (void)initialize {

   NSMutableDictionary *defaultValues = [NSMutableDictionary dictionary];

   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDisplayEBSourceKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDisplayEBObjectKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDisplayEBLocationKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDisplayEBBeginDateKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDisplayEBEndDateKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDisplayEBActorKey];

   [defaultValues setObject:[NSNumber numberWithInt:preferenceTimeRowDateAndTimeTag] forKey:SSDateDisplayKey];

   [defaultValues setObject:[NSNumber numberWithInt:preferenceJumpMapInChartTag] forKey:SSDisplayJumpMapKey];

   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDisplayChartLegendKey];

   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSEBTableActorColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSEBTableActionColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSEBTableObjectColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSEBTableLocationColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSEBTableSourceColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSEBTableRemarkColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSEBTableBegindateColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSEBTableEnddateColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSEBTableBegintimeColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSEBTableEndtimeColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSEBTableXpositionColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSEBTableLabelColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSEBTableDurationColumnKey];

   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDiamondTableNumberColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDiamondTableOwnertypeColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDiamondTableOwnerdescriptionColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDiamondTableAnalystColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDiamondTableFileidColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDiamondTableDescriptionColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDiamondTableDiamondstateColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDiamondTableUdvalue1ColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDiamondTableUdvalue2ColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDiamondTableUdvalue3ColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDiamondTableUdvalue4ColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDiamondTableUdvalue5ColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDiamondTableUdvalue6ColumnKey];

   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDiamondOptionTableUdvalue1ColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDiamondOptionTableUdvalue2ColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDiamondOptionTableUdvalue3ColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDiamondOptionTableUdvalue4ColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDiamondOptionTableUdvalue5ColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDiamondOptionTableOptionColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDiamondOptionTableIndexColumnKey];

   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDiamondTradeoffTableProColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDiamondTradeoffTableConColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDiamondTradeoffTableUdvalue1ColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDiamondTradeoffTableUdvalue2ColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDiamondTradeoffTableUdvalue3ColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDiamondTradeoffTableIndexColumnKey];

   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSCommentTableCommentstringColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSCommentTableXpositionColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSCommentTableYpositionColumnKey];
   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSCommentTableTypeColumnKey];
   
   [defaultValues setObject:[NSNumber numberWithInt:preferenceStartupNewFileTag] forKey:SSStartupOptionKey];
   
   [defaultValues setObject:[NSString string] forKey:SSLastSavedFileKey];

   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSSaveBackupKey];
   [defaultValues setObject:[NSNumber numberWithInt:10] forKey:SSSaveBackupFrequencyKey];

   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSFirstRunKey];

   [defaultValues setObject:@"Final EB" forKey:SSDefaultWhiteLabelDesignationKey];
   [defaultValues setObject:@"Hypothesized EB" forKey:SSDefaultYellowLabelDesignationKey];
   [defaultValues setObject:@"Inferred EB" forKey:SSDefaultGreenLabelDesignationKey];
   [defaultValues setObject:@"Temporary EB" forKey:SSDefaultLightBlueLabelDesignationKey];
   [defaultValues setObject:@"Required EB" forKey:SSDefaultBlueLabelDesignationKey];
   [defaultValues setObject:@"Questionable EB" forKey:SSDefaultPurpleLabelDesignationKey];
   [defaultValues setObject:@"Incomplete EB" forKey:SSDefaultOrangeLabelDesignationKey];
   [defaultValues setObject:@"Disputed EB" forKey:SSDefaultRedLabelDesignationKey];
   [defaultValues setObject:[NSString string] forKey:SSDefaultTitleKey];
   [defaultValues setObject:NSUserName() forKey:SSDefaultAuthorKey];
   [defaultValues setObject:[NSCalendarDate calendarDate] forKey:SSDefaultDateKey];

   [defaultValues setObject:@"Exposure" forKey:SSDefaultDiamondUDValue1Key];
   [defaultValues setObject:@"Kind" forKey:SSDefaultDiamondUDValue2Key];
   [defaultValues setObject:@"Probability" forKey:SSDefaultDiamondUDValue3Key];
   [defaultValues setObject:@"Severity" forKey:SSDefaultDiamondUDValue4Key];
   [defaultValues setObject:@"Risk Rating" forKey:SSDefaultDiamondUDValue5Key];
   [defaultValues setObject:@"Significance" forKey:SSDefaultDiamondUDValue6Key];
   [defaultValues setObject:@"Risk" forKey:SSDefaultDiamondOptionUDValue1Key];
   [defaultValues setObject:@"Phase" forKey:SSDefaultDiamondOptionUDValue2Key];
   [defaultValues setObject:@"Type" forKey:SSDefaultDiamondOptionUDValue3Key];
   [defaultValues setObject:@"New Risk" forKey:SSDefaultDiamondOptionUDValue4Key];
   [defaultValues setObject:@"Follow Up" forKey:SSDefaultDiamondOptionUDValue5Key];
   [defaultValues setObject:@"Weight" forKey:SSDefaultDiamondTradeoffUDValue1Key];
   [defaultValues setObject:@"Rank" forKey:SSDefaultDiamondTradeoffUDValue2Key];
   [defaultValues setObject:@"Weight" forKey:SSDefaultDiamondTradeoffUDValue3Key];

   [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:SSDisplayDupeWarningKey];

   [defaultValues setObject:@"~/Documents" forKey:SSDefaultProjectFolderKey];

   [defaultValues setObject:@"" forKey:SSCatalystSerialNumberKey];

   NSMutableArray *defaultPoisonWords = [NSMutableArray array];
   [defaultPoisonWords addObject:[NSMutableDictionary dictionaryWithObjects:[NSArray arrayWithObjects:NSLocalizedString(@"Was", nil), NSLocalizedString(@"WasActionWarning", nil), nil]
                                                                    forKeys:[NSArray arrayWithObjects:@"word", @"warning", nil]]];
   [defaultPoisonWords addObject:[NSMutableDictionary dictionaryWithObjects:[NSArray arrayWithObjects:NSLocalizedString(@"Not", nil), NSLocalizedString(@"NotActionWarning", nil), nil]
                                                                    forKeys:[NSArray arrayWithObjects:@"word", @"warning", nil]]];

   [defaultValues setObject:defaultPoisonWords forKey:SSDefaultPoisonWordListKey];
   
   // Register the dictionary of defaults
   [[NSUserDefaults standardUserDefaults] registerDefaults: defaultValues];
}

- (id)init
{
   if (self = [super init]) {
      preferenceController = nil;

      NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
      [nc addObserver:self
             selector:@selector(exportImage:)
                 name:@"SSExportChartImage"
               object:nil];

      [nc addObserver:self
             selector:@selector(showInspectorPanel:)
                 name:@"SSShowInspector"
               object:nil];
      [nc addObserver:self
             selector:@selector(showJumpMapPanel:)
                 name:@"SSShowJumpMapPanel"
               object:nil];

      [nc addObserver:self
             selector:@selector(setBackupTimer)
                 name:@"SSSaveBackupChanged"
               object:nil];

      lastJumpMapDisplayStyle = [[NSUserDefaults standardUserDefaults] integerForKey:SSDisplayJumpMapKey]; //for next time it changes
   }

   if([[NSUserDefaults standardUserDefaults] integerForKey:SSDisplayJumpMapKey] == preferenceJumpMapInWindowTag) {
      [self showJumpMapPanel:self];
   }

   [self setBackupTimer];
   
   return self;
}

- (IBAction)newDoc:(id)sender
{
   [[SSNewDocController sharedNewDocController] initiateNewDocument];
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
   //uncomment to activate expiration code
//   [self setExpirationDetails];
  // [self validateExpirationDetails];

   [self installEngine];
   [self updateSN];

   if(![self isRegistered]) {
      int choice = NSRunAlertPanel(@"Unregistered", @"This copy of Investigation Catalyst is Unregistered. If you would like to register and remove the 20 Event Block limit, please select \"Register\" below.", @"Register", @"Use Unlicensed", nil);
      if(choice == NSAlertDefaultReturn) {
         [self menuPurchase:self];
      }
   }
}

- (void)setExpirationDetails
{
   NSMutableArray *array;
   NSCalendarDate *today = [NSCalendarDate calendarDate];
   NSFileManager *fm = [NSFileManager defaultManager];
   NSString *dateFilePath = [NSHomeDirectory() stringByAppendingString:@"/Library/Preferences/.SS4Store"];

   if([fm fileExistsAtPath:dateFilePath]) { //program has been used before
      //update the last used date
      array = [[NSUnarchiver unarchiveObjectWithFile:dateFilePath] retain];

      if([[array objectAtIndex:1] dayOfCommonEra] < [today dayOfCommonEra]) {
         //sets last use date to today if today is after the last date entered this will stop people turning back their clocks
         [array replaceObjectAtIndex:1 withObject:today];
         [NSArchiver archiveRootObject:array toFile:dateFilePath];
      }
      [array release];
   } else { //this is first use or they have deleted the file
      //create a new file for expiration with todays date
      array = [[NSMutableArray alloc] init];
      [array addObject:today];
      [array addObject:today];
      [NSArchiver archiveRootObject:array toFile:dateFilePath];
      [array release];
   }
}

- (void)validateExpirationDetails
{
   NSString *dateFilePath = [NSHomeDirectory() stringByAppendingString:@"/Library/Preferences/.SS4Store"];
   NSMutableArray *array = [[NSUnarchiver unarchiveObjectWithFile:dateFilePath] retain];
   NSCalendarDate *today = [NSCalendarDate calendarDate];
   
   if([[array objectAtIndex:0] dayOfCommonEra] + 30 > [[array objectAtIndex:1] dayOfCommonEra]
      && [[array objectAtIndex:1] dayOfCommonEra] <= [today dayOfCommonEra]) { //still in 32 day limit and they haven't set their clock back
      [array release];
      NSRunAlertPanel(NSLocalizedString(@"Alert", nil), [NSString stringWithFormat:@"This beta release of Investigation Catalyst will expire in %d days.", (([[array objectAtIndex:0] dayOfCommonEra] + 30) - [today dayOfCommonEra])], @"OK", nil, nil);
   } else { //expired
      NSRunAlertPanel(NSLocalizedString(@"Alert", nil), @"This beta release of Investigation Catalyst has expired. Please visit <address> to obtain the latest version.", @"OK", nil, nil);
      //shutdown the app
      [[NSApplication sharedApplication] terminate:nil];
   }
}

- (void)awakeFromNib
{
   //set the state of the titleBoxMenuItem
   if([[NSUserDefaults standardUserDefaults] boolForKey:SSDisplayChartLegendKey]) {
      [titleBoxMenuItem setState:NSOnState];
   } else {
      [titleBoxMenuItem setState:NSOffState];
   }

   //set the state of the jump map menu items
   switch([[NSUserDefaults standardUserDefaults] integerForKey:SSDisplayJumpMapKey]) {
      case preferenceJumpMapInChartTag:
         [jumpMapInChartMenuItem setState:NSOnState];
         [jumpMapInWindowMenuItem setState:NSOffState];
         [jumpMapNoDisplayMenuItem setState:NSOffState];
         break;
      case preferenceJumpMapInWindowTag:
         [jumpMapInChartMenuItem setState:NSOffState];
         [jumpMapInWindowMenuItem setState:NSOnState];
         [jumpMapNoDisplayMenuItem setState:NSOffState];
         break;
      case preferenceJumpMapNoDisplayTag:
         [jumpMapInChartMenuItem setState:NSOffState];
         [jumpMapInWindowMenuItem setState:NSOffState];
         [jumpMapNoDisplayMenuItem setState:NSOnState];
         break;
      default:
         break;
   }
}

//***********************************application delegate methods
- (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender
{
   if(hasLaunched) {
      [[SSNewDocController sharedNewDocController] initiateNewDocument];
   } else {
      //the app is in the proces of loading so lets see what the user wants
      hasLaunched = YES;
      NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
      
      if([defaults boolForKey:SSFirstRunKey]) {
         //this is the first time the user has run Catalyst so create a new file and open the quick start tutorial

         [defaults setObject:[NSNumber numberWithBool:NO] forKey:SSFirstRunKey];

         //create the new document
         id theDocument = [[NSDocumentController sharedDocumentController] openUntitledDocumentOfType:@"Catalyst Document" display:YES];
         [theDocument setFileName:@"~/Documents/My_First_File.mes"];
         [theDocument setProjectFolder:@"~/Documents"];
         [defaults setObject:@"~/Documents" forKey:SSDefaultProjectFolderKey];

         //create the first EB
         SSEventObject *event = [[[SSEventObject alloc] initWithActor:@"you"
                                                               action:@"opened"
                                                               object:@"your first Project File"
                                                             location:@"on your computer"
                                                            beginTime:[SSChartDate calendarDate]
                                                              endTime:[[SSChartDate calendarDate] addTimeInterval:86400]
                                                               source:[NSArray arrayWithObject:@"First Projrect file"]
                                                               remark:@"(you can erase this EB later)"
                                                              address:[theDocument addressForNewEvent]
                                                                label:[NSNumber numberWithInt:SSWhiteLabelType]] autorelease];
         //add the event
         [theDocument addNewEventBlock:event];

         //open the quickstart file
         //get the path to the page we want
         NSString *path = [NSString stringWithFormat:@"help://%@/ICHelp/QuickStart.html", [[NSBundle mainBundle] pathForResource:@"ICHelp" ofType: @""]];

         //make the path url safe
         path = (NSString*)CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef) path,
                                                                   NULL, NULL, kCFStringEncodingUTF8);
         // create and open the NSURL to our page
         [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:path]];
         
      } else {
         //they have used the app before so do the users prefered action
         switch([[NSUserDefaults standardUserDefaults] integerForKey:SSStartupOptionKey]) {
            case preferenceStartupDoNothingTag:return NO;
               break;
            case preferenceStartupShowOpenFileDialogTag:
               if(!openPanelHasBeenLaunched) {
                  openPanelHasBeenLaunched = YES;
                  [[NSDocumentController sharedDocumentController] openDocument:self];
               }
               return NO;
               break;
            case preferenceStartupOpenLastFileTag:
               [[NSDocumentController sharedDocumentController] openDocumentWithContentsOfFile:[[NSUserDefaults standardUserDefaults] objectForKey:SSLastSavedFileKey]
                                                                                       display:YES];
               return NO;
               break;
            default:
               [[SSNewDocController sharedNewDocController] initiateNewDocument];
               break;
         }
      }
   }

   return NO;
}

//***********************************

- glossarySavePanelAccessoryView
{
   //returns the accessory view used in the export glossary save panel
   if (glossarySavePanelAccessoryView == nil) {
      [NSBundle loadNibNamed:@"GlossarySavePanelAccessoryView.nib" owner:self];
      [glossarySavePanelAccessoryView retain];
   }

   return glossarySavePanelAccessoryView;
}

- imageSavePanelAccessoryView
{
   //returns the accessory view used in the export image save panel
   if (imageSavePanelAccessoryView == nil) {
      [NSBundle loadNibNamed:@"ImageSavePanelAccessoryView.nib" owner:self];
      [imageSavePanelAccessoryView retain];
   }

   return imageSavePanelAccessoryView;
}

- (void)showPreferencePanel:(id)sender
{
   // Is preferenceController nil?
   if (!preferenceController) {
      preferenceController = [[SSPreferenceController alloc] init];
   }
   [preferenceController showWindow:self];
}

- (IBAction)showInspectorPanel:(id)sender
{
   [[SSInspectorController sharedInspectorController] showWindow:sender];
}

- (IBAction)showDiamondPanel:(id)sender
{
   [[SSNeedsDiamondsPanelController sharedDiamondPanelController] showWindow:sender];
}

- (IBAction)showNewEBPanel:(id)sender
{
   [[SSSharedNewEBPanelController sharedNewEBController] showWindow:self];
}

- (IBAction)showEBPanel:(id)sender
{
   [[SSEBPanelController sharedEBPanelController] showWindow:sender];
}

- (IBAction)showCommentPanel:(id)sender
{
   [[SSCommentPanelController sharedCommentPanelController] showWindow:sender];
}

- (IBAction)showJumpMapPanel:(id)sender
{
   [[SSJumpMapPanelController sharedJumpMapPanelController] showWindow:sender];
}

- (IBAction)showMatrixPropertiesPanel:(id)sender
{
   [[SSMatrixPropertiesPanel sharedMatrixPropertiesPanelController] showWindow:sender];
}

- (IBAction)showObjectFilterPanel:(id)sender
{
   [[SSObjectFilterPanelController sharedObjectFilterPanelController] showWindow:sender];
}

- (IBAction)showOverlapScaleAndRangePanel:(id)sender
{
   [[SSOverlapScaleAndRangePanelController sharedOverlapScaleAndRangePanelController] showWindow:sender];
}

- (IBAction)showDiamondLabelPanel:(id)sender
{
  [[SSDiamondLabelPanelController sharedDiamondLabelPanelController] showWindow:sender];  
}

- (IBAction)showRulesPanel:(id)sender
{
   //[[SSRulesPanelController sharedRulesPanelController] showWindow:sender];
   NSString *path = [NSString stringWithFormat:@"help://%@/ICHelp/IC Rules.htm", [[NSBundle mainBundle] pathForResource:@"ICHelp" ofType: @""]];

   //make the path url safe
   path = (NSString*)CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef) path,
                                                             NULL, NULL, kCFStringEncodingUTF8);
   // create and open the NSURL to our page
   [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:path]];
}

- (IBAction)showSerialNumberPanel:(id)sender
{
   SSSerialNumberPanelController *serialPanelController = [[SSSerialNumberPanelController alloc] init];
   [serialPanelController showWindow:sender];
}

- (IBAction)showPoisonWordsPanel:(id)sender
{
   SSPoisonWordPanelController *sharedPoisonWordController = [[SSPoisonWordPanelController alloc] init];
   [sharedPoisonWordController showWindow:sender];
}

- (IBAction)importFiles:(id)sender
{
   [[[NSDocumentController sharedDocumentController] currentDocument] importFiles];
}

- (IBAction)changeTitleBoxDisplay:(id)sender
{
   //set the correct value in user preferences and change state of menu item
   if([sender state] == NSOnState) {
      [[NSUserDefaults standardUserDefaults] setBool:NO forKey:SSDisplayChartLegendKey];
      [titleBoxMenuItem setState:NSOffState];
   } else {
      [[NSUserDefaults standardUserDefaults] setBool:YES forKey:SSDisplayChartLegendKey];
      [titleBoxMenuItem setState:NSOnState];
   }

   //notify documents to change the display of legend view
   [[NSNotificationCenter defaultCenter] postNotificationName:@"SSLegendDisplayChanged"
                                                       object:nil];
}

- (IBAction)changeJumpMapDisplay:(id)sender
{
   //this method determines what notifications to send and actions to perform based on the current and last jump map display option

   [[NSUserDefaults standardUserDefaults] setInteger:[sender tag]
                                              forKey:SSDisplayJumpMapKey];

   switch([[NSUserDefaults standardUserDefaults] integerForKey:SSDisplayJumpMapKey]) {
      case preferenceJumpMapInChartTag:[[NSNotificationCenter defaultCenter] postNotificationName:@"SSAddJumpMapToChart"
                                                                                           object:nil];
         if(lastJumpMapDisplayStyle == preferenceJumpMapInWindowTag) {
            //the jumpmap is currently displayed in a window so close the window
            [[SSJumpMapPanelController sharedJumpMapPanelController] close:self];
         }
         [jumpMapInChartMenuItem setState:NSOnState];
         [jumpMapInWindowMenuItem setState:NSOffState];
         [jumpMapNoDisplayMenuItem setState:NSOffState];
            break;
      case preferenceJumpMapInWindowTag:[[NSNotificationCenter defaultCenter] postNotificationName:@"SSShowJumpMapPanel"
                                                                                            object:nil];
         if(lastJumpMapDisplayStyle == preferenceJumpMapInChartTag) {
            //the jumpmap is currently displayed in the chart notify all documents to remove them
            [[NSNotificationCenter defaultCenter] postNotificationName:@"SSRedisplayChart"
                                                                object:nil];
         }
         [jumpMapInChartMenuItem setState:NSOffState];
         [jumpMapInWindowMenuItem setState:NSOnState];
         [jumpMapNoDisplayMenuItem setState:NSOffState];
            break;
      case preferenceJumpMapNoDisplayTag:
         if(lastJumpMapDisplayStyle == preferenceJumpMapInChartTag) {
            //the jumpmap is currently displayed in the chart notify all documents to remove them
            [[NSNotificationCenter defaultCenter] postNotificationName:@"SSRemoveJumpMapFromChart"
                                                                object:nil];
         } else {
            //the jumpmap is currently displayed in a window so close the window
            [[SSJumpMapPanelController sharedJumpMapPanelController] close:self];

         }
         [jumpMapInChartMenuItem setState:NSOffState];
         [jumpMapInWindowMenuItem setState:NSOffState];
         [jumpMapNoDisplayMenuItem setState:NSOnState];
         break;
      default:
         break;
   }

   lastJumpMapDisplayStyle = [[NSUserDefaults standardUserDefaults] integerForKey:SSDisplayJumpMapKey]; //for next time it changes
}


- (IBAction)exportImage:(id)sender
{
   //gets the required data from the current chart and saves it with the name and location provided by user
   
   NSSavePanel *savePanel = [NSSavePanel savePanel];
   int result;
   NSData *imageData;
   NSBitmapImageRep *sourceBitmap;
   NSDictionary *properties;
   NSString *path;

   [savePanel setTitle:@"Export Matrix Image"];
   [savePanel setAccessoryView:[self imageSavePanelAccessoryView]];
   result = [savePanel runModalForDirectory:nil file:@""];

   if(result == NSOKButton) {
      path = [savePanel filename];
      
     switch([[imageTypePopUp selectedItem] tag]) {
        case SSExportJpegType:
           path = [path stringByAppendingString:@".jpeg"];
           sourceBitmap = [[[NSDocumentController sharedDocumentController] currentDocument] chartImage];
           properties = [NSDictionary dictionaryWithObjectsAndKeys:
              [NSNumber numberWithFloat:1.0], NSImageCompressionFactor, nil];

           imageData = [sourceBitmap representationUsingType:NSJPEGFileType
                                                  properties:properties];

           [imageData writeToFile:path atomically:YES];
             break; 
        case SSExportPngType:
           path = [path stringByAppendingString:@".png"];
           sourceBitmap = [[[NSDocumentController sharedDocumentController] currentDocument] chartImage];
           properties = [NSDictionary dictionaryWithObjectsAndKeys:
              [NSNumber numberWithFloat:1.0], NSImageCompressionFactor, nil];

           imageData = [sourceBitmap representationUsingType:NSPNGFileType
                                                  properties:properties];

           [imageData writeToFile:path atomically:YES];
             break;
        case SSExportTiffType:
           path = [path stringByAppendingString:@".tiff"];
           sourceBitmap = [[[NSDocumentController sharedDocumentController] currentDocument] chartImage];

           imageData = [sourceBitmap TIFFRepresentationUsingCompression:NSTIFFCompressionLZW
                                                                 factor:1.0];

           [imageData writeToFile:path atomically:YES];
             break;
         default:
           break;
     } 
   }
}

- (IBAction)exportGlossary:(id)sender
{
   //gets the required data from the current chart and saves it with the name and location provided by user

   NSSavePanel *savePanel = [NSSavePanel savePanel];
   int result;
   NSData *glossaryData;
   NSString *path;

   [savePanel setTitle:@"Export Matrix Glossary"];
   [savePanel setAccessoryView:[self glossarySavePanelAccessoryView]];
   result = [savePanel runModalForDirectory:nil file:@""];

   if(result == NSOKButton) {
      path = [savePanel filename];

      switch([[glossaryTypePopUp selectedItem] tag]) {
         case SSExportActorGlossaryType:
            path = [path stringByAppendingString:@".txt"];
            glossaryData = [[[NSDocumentController sharedDocumentController] currentDocument] glossaryDataForType:@"actor"];

            [glossaryData writeToFile:path atomically:YES];
            break;
         case SSExportActionGlossaryType:
            path = [path stringByAppendingString:@".txt"];
            glossaryData = [[[NSDocumentController sharedDocumentController] currentDocument] glossaryDataForType:@"action"];

            [glossaryData writeToFile:path atomically:YES];
            break;
         case SSExportLocationGlossaryType:
            path = [path stringByAppendingString:@".txt"];
            glossaryData = [[[NSDocumentController sharedDocumentController] currentDocument] glossaryDataForType:@"location"];

            [glossaryData writeToFile:path atomically:YES];
            break;
         case SSExportObjectGlossaryType:
            path = [path stringByAppendingString:@".txt"];
            glossaryData = [[[NSDocumentController sharedDocumentController] currentDocument] glossaryDataForType:@"object"];

            [glossaryData writeToFile:path atomically:YES];
            break;
         case SSExportSourceGlossaryType:
            path = [path stringByAppendingString:@".txt"];
            glossaryData = [[[NSDocumentController sharedDocumentController] currentDocument] glossaryDataForType:@"source"];

            [glossaryData writeToFile:path atomically:YES];
            break;
         case SSExportOptionGlossaryType:
            path = [path stringByAppendingString:@".txt"];
            glossaryData = [[[NSDocumentController sharedDocumentController] currentDocument] optionGlossaryData];

            [glossaryData writeToFile:path atomically:YES];
            break;
         case SSExportProTradeoffGlossaryType:
            path = [path stringByAppendingString:@".txt"];
            glossaryData = [[[NSDocumentController sharedDocumentController] currentDocument] proTradeoffGlossaryData];

            [glossaryData writeToFile:path atomically:YES];
            break;
         case SSExportConTradeoffGlossaryType:
            path = [path stringByAppendingString:@".txt"];
            glossaryData = [[[NSDocumentController sharedDocumentController] currentDocument] conTradeoffGlossaryData];

            [glossaryData writeToFile:path atomically:YES];
            break;
         default:
            break;
      }
   }
}

- (IBAction)exportRemarkList:(id)sender
{
   //gets the required data from the current chart and saves it with the name and location provided by user
   NSSavePanel *savePanel = [NSSavePanel savePanel];
   int result;
   NSData *data;
   NSString *path;

   [savePanel setTitle:@"Export Remarks For Report"];
   result = [savePanel runModalForDirectory:nil file:@""];

   if(result == NSOKButton) {
      path = [savePanel filename];
      path = [path stringByAppendingString:@".txt"];
      data = [[[NSDocumentController sharedDocumentController] currentDocument] remarkListData];

      [data writeToFile:path atomically:YES];
   }
}

- (IBAction)exportEventList:(id)sender
{
   //gets the required data from the current chart and saves it with the name and location provided by user
   NSSavePanel *savePanel = [NSSavePanel savePanel];
   int result;
   NSData *data;
   NSString *path;

   [savePanel setTitle:@"Export EBs For Report"];
   result = [savePanel runModalForDirectory:nil file:@""];

   if(result == NSOKButton) {
      path = [savePanel filename];
      path = [path stringByAppendingString:@".txt"];
      data = [[[NSDocumentController sharedDocumentController] currentDocument] eventListData];

      [data writeToFile:path atomically:YES];
   }
}

- (IBAction)exportCommentList:(id)sender
{
   //gets the required data from the current chart and saves it with the name and location provided by user
   NSSavePanel *savePanel = [NSSavePanel savePanel];
   int result;
   NSData *data;
   NSString *path;

   [savePanel setTitle:@"Export Comments For Report"];
   result = [savePanel runModalForDirectory:nil file:@""];

   if(result == NSOKButton) {
      path = [savePanel filename];
      path = [path stringByAppendingString:@".txt"];
      data = [[[NSDocumentController sharedDocumentController] currentDocument] commentListData];

      [data writeToFile:path atomically:YES];
   }
}

- (IBAction)exportDiamondList:(id)sender
{
   //gets the required data from the current chart and saves it with the name and location provided by user
   NSSavePanel *savePanel = [NSSavePanel savePanel];
   int result;
   NSData *data;
   NSString *path;

   [savePanel setTitle:@"Export Diamonds For Report"];
   result = [savePanel runModalForDirectory:nil file:@""];

   if(result == NSOKButton) {
      path = [savePanel filename];
      path = [path stringByAppendingString:@".csv"];
      data = [[[NSDocumentController sharedDocumentController] currentDocument] diamondListData];

      [data writeToFile:path atomically:YES];
   }
}

- (IBAction)snapChartToTimes:(id)sender
{
   //get the current document to order event blocks
   [[[NSDocumentController sharedDocumentController] currentDocument] snapChartToTimes];
}

- (IBAction)snapTimesToChart:(id)sender
{
   //get the current document to set eb times
   [[[NSDocumentController sharedDocumentController] currentDocument] snapTimesToChart];
}

- (IBAction)addDiamond:(id)sender
{
   [[[NSDocumentController sharedDocumentController] currentDocument] addNeedsDiamondToSelectedObject];
}

- (IBAction)addComment:(id)sender
{
   [[[NSDocumentController sharedDocumentController] currentDocument] addCommentOfType:[NSNumber numberWithInt:SSCommentQuestionType]];
}

- (IBAction)zoomIn:(id)sender
{
   [[[NSDocumentController sharedDocumentController] currentDocument] zoomIn];
}

- (IBAction)zoomOut:(id)sender
{
   [[[NSDocumentController sharedDocumentController] currentDocument] zoomOut];
}

- (IBAction)zoomOverlapIn:(id)sender
{
   [[[NSDocumentController sharedDocumentController] currentDocument] zoomOverlapIn];
}

- (IBAction)zoomOverlapOut:(id)sender
{
   [[[NSDocumentController sharedDocumentController] currentDocument] zoomOverlapOut];
}

- (IBAction)switchViewType:(id)sender
{
   [[[NSDocumentController sharedDocumentController] currentDocument] switchDisplayMode];
}
//***********************************
- (void)setBackupTimer
{
   //sets a timer to backup files based on the user preferences
   NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

   if(backupTimer != nil) {
      [backupTimer invalidate];
      [backupTimer release];
      backupTimer = nil;
   }
   
   
   if([defaults boolForKey:SSSaveBackupKey]) {
      //user wants to backup files
      backupTimer = [[NSTimer scheduledTimerWithTimeInterval:([defaults integerForKey:SSSaveBackupFrequencyKey] * 60) target:self selector:@selector(backupOpenFiles:) userInfo:nil repeats:YES] retain];
   }
}

- (void)backupOpenFiles:(NSTimer *)timer
{
   NSEnumerator *enumerator = [[[NSDocumentController sharedDocumentController] documents] objectEnumerator];
   id anObject;

   while (anObject = [enumerator nextObject]) {
      [anObject saveBackupCopy];
   }
}



//***********************************opening tutorials

- (IBAction)openFastStartTutorial:(id)sender
{
   if(floor(NSAppKitVersionNumber) >= 743) {
      [[NSHelpManager sharedHelpManager] openHelpAnchor:@"FastStartTutorial" inBook:@"Investigation Catalyst Help"];
   } else {
      //get the path to the page we want
      NSString *path = [NSString stringWithFormat:@"help://%@/Tutorials/Fast_Start_tutorial/FastStart.html", [[NSBundle mainBundle] pathForResource:@"ICHelp" ofType: @""]];

      //make the path url safe
      path = (NSString*)CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef) path,
                                                                NULL, NULL, kCFStringEncodingUTF8);
      // create and open the NSURL to our page
      [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:path]];
   }
}

- (IBAction)openIncidentInvestigationTutorial:(id)sender
{
   if(floor(NSAppKitVersionNumber) >= 743) {
      [[NSHelpManager sharedHelpManager] openHelpAnchor:@"IncidentInvestigationTutorial" inBook:@"Investigation Catalyst Help"];
   } else {
      //get the path to the page we want
      NSString *path = [NSString stringWithFormat:@"help://%@/Tutorials/Investigation_tutorial/ii_main.html", [[NSBundle mainBundle] pathForResource:@"ICHelp" ofType: @""]];

      //make the path url safe
      path = (NSString*)CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef) path,
                                                                NULL, NULL, kCFStringEncodingUTF8);
      // create and open the NSURL to our page
      [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:path]];
   }
}

- (IBAction)openHazardAnalysisTutorial:(id)sender
{
   if(floor(NSAppKitVersionNumber) >= 743) {
      [[NSHelpManager sharedHelpManager] openHelpAnchor:@"HazardAnalysesTutorial" inBook:@"Investigation Catalyst Help"];
   } else {
      //get the path to the page we want
      NSString *path = [NSString stringWithFormat:@"help://%@/Tutorials/Hazard_analysis_tutorial/ha_main.html", [[NSBundle mainBundle] pathForResource:@"ICHelp" ofType: @""]];

      //make the path url safe
      path = (NSString*)CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef) path,
                                                                NULL, NULL, kCFStringEncodingUTF8);
      // create and open the NSURL to our page
      [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:path]];
   }  
}

- (IBAction)openQualityAssuranceTutorial:(id)sender
{
   if(floor(NSAppKitVersionNumber) >= 743) {
      [[NSHelpManager sharedHelpManager] openHelpAnchor:@"QualityAssuranceTutorial" inBook:@"Investigation Catalyst Help"];
   } else {
      //get the path to the page we want
      NSString *path = [NSString stringWithFormat:@"help://%@/Tutorials/QA_tutorial/TR1.html", [[NSBundle mainBundle] pathForResource:@"ICHelp" ofType: @""]];

      //make the path url safe
      path = (NSString*)CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef) path,
                                                                NULL, NULL, kCFStringEncodingUTF8);
      // create and open the NSURL to our page
      [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:path]];
   } 
}

- (IBAction)openWitnessAnalysisTutorial:(id)sender
{
   if(floor(NSAppKitVersionNumber) >= 743) {
      [[NSHelpManager sharedHelpManager] openHelpAnchor:@"WitnessAnalysisTutorial" inBook:@"Investigation Catalyst Help"];
   } else {
      //get the path to the page we want
      NSString *path = [NSString stringWithFormat:@"help://%@/Tutorials/Witness_Tutorial/TS1.html", [[NSBundle mainBundle] pathForResource:@"ICHelp" ofType: @""]];

      //make the path url safe
      path = (NSString*)CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef) path,
                                                                NULL, NULL, kCFStringEncodingUTF8);
      // create and open the NSURL to our page
      [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:path]];
   }
}

- (IBAction)openChangeManagementTutorial:(id)sender
{
   if(floor(NSAppKitVersionNumber) >= 743) {
      [[NSHelpManager sharedHelpManager] openHelpAnchor:@"ChangeManagementTutorial" inBook:@"Investigation Catalyst Help"];
   } else {
      NSString *path = [NSString stringWithFormat:@"help://%@/Tutorials/Change_manage_tutorial/cm_main.html", [[NSBundle mainBundle] pathForResource:@"ICHelp" ofType: @""]];

      //make the path url safe
      path = (NSString*)CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef) path,
                                                                NULL, NULL, kCFStringEncodingUTF8);
      // create and open the NSURL to our page
      [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:path]];
   }
   
}

- (IBAction)openRecommendationDevelopmentTutorial:(id)sender
{
   if(floor(NSAppKitVersionNumber) >= 743) {
      [[NSHelpManager sharedHelpManager] openHelpAnchor:@"RecommendationDevelopmentTutorial" inBook:@"Investigation Catalyst Help"];
   } else {
      //get the path to the page we want
      NSString *path = [NSString stringWithFormat:@"help://%@/Tutorials/Recommendation_tutorial/rec_main.html", [[NSBundle mainBundle] pathForResource:@"ICHelp" ofType: @""]];

      //make the path url safe
      path = (NSString*)CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef) path,
                                                                NULL, NULL, kCFStringEncodingUTF8);
      // create and open the NSURL to our page
      [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:path]];
   }
}

//***********************************

- (BOOL)isRegistered
{
   return registered;
}

- (void)setRegistered:(BOOL)b
{
   registered = b;
}

//***********************************

- (BOOL)validateMenuItem:(NSMenuItem *)anItem {
   SSCatalystDocument *currentDocument = [[NSDocumentController sharedDocumentController] currentDocument];
   
   if ([[anItem title] isEqualToString:NSLocalizedString(@"Image...", nil)]) { //validating the Image... menu item
      if(!currentDocument) { //if there is no doc open
         return NO;
      }
   }

   if ([[anItem title] isEqualToString:NSLocalizedString(@"Glossary...", nil)]) { //validating the Glossary... menu item
      if(!currentDocument) { //if there is no doc open
         return NO;
      }
   }

   if ([[anItem title] isEqualToString:NSLocalizedString(@"EBs For Report...", nil)]) { //validating the EBs For Report... menu item
      if(!currentDocument) { //if there is no doc open
         return NO;
      }
   }

   if ([[anItem title] isEqualToString:NSLocalizedString(@"Comments For Report...", nil)]) { //validating the Comments For Report... menu item
      if(!currentDocument) { //if there is no doc open
         return NO;
      }
   }

   if ([[anItem title] isEqualToString:NSLocalizedString(@"Diamonds For Report...", nil)]) { //validating the Diamonds For Report... menu item
      if(!currentDocument) { //if there is no doc open
         return NO;
      }
   }

   if ([[anItem title] isEqualToString:NSLocalizedString(@"Remarks For Report...", nil)]) { //validating the Remarks For Report... menu item
      if(!currentDocument) { //if there is no doc open
         return NO;
      }
   }

   if ([[anItem title] isEqualToString:NSLocalizedString(@"New EB Panel", nil)]) { //validating the New EB Panel menu item
      if(!currentDocument) { //if there is no doc open
         return NO;
      }
   }

   if ([[anItem title] isEqualToString:NSLocalizedString(@"New Diamond", nil)]) { //validating the New Diamond menu item
      if(!currentDocument || ![currentDocument canAddNeedsDiamond]) { //if there is no doc open
         return NO;
      }
   }

   if ([[anItem title] isEqualToString:NSLocalizedString(@"New Comment", nil)]) { //validating the New Comment menu item
      if(!currentDocument || [currentDocument displayMode] != SSMatrixDisplayMode) { //if there is no doc open
         return NO;
      }
   }

   if ([[anItem title] isEqualToString:NSLocalizedString(@"Snap EBs To Time", nil)]) { //validating the Snap EBs To Time menu item
      if(!currentDocument || [currentDocument displayMode] != SSMatrixDisplayMode) { //if there is no doc open
         return NO;
      }
   }

   if ([[anItem title] isEqualToString:NSLocalizedString(@"Snap Times To Matrix", nil)]) { //validating the Snap Times To Matrix menu item
      if(!currentDocument || [currentDocument displayMode] != SSMatrixDisplayMode) { //if there is no doc open
         return NO;
      }
   }

   if ([[anItem title] isEqualToString:NSLocalizedString(@"Import...", nil)]) { //validating the import menu item
      if(!currentDocument) { //if there is no doc open
         return NO;
      }
   }

   if ([[anItem title] isEqualToString:NSLocalizedString(@"AddDiamond", nil)]) {
      if(!currentDocument || [[currentDocument selectedObjects] count] != 1) {
         return NO;
      } else {
         if(![[[currentDocument selectedObjects] objectAtIndex:0] isKindOfClass:[SSEventView class]] && ![[[currentDocument selectedObjects] objectAtIndex:0] isKindOfClass:[SSEventLinkObject class]]) {
            //the selected object cant have a diamond so disable
            return NO;
         }
      }
   }

   if ([[anItem title] isEqualToString:NSLocalizedString(@"AddComment", nil)]) {
      if(!currentDocument || [currentDocument displayMode] != SSMatrixDisplayMode) {
         return NO;
      }
   }

   if ([[anItem title] isEqualToString:NSLocalizedString(@"ZoomIn", nil)]) {
      if(!currentDocument || ![currentDocument canZoomIn]) {
         return NO;
      }
   }

   if ([[anItem title] isEqualToString:NSLocalizedString(@"ZoomOut", nil)]) {
      if(!currentDocument || ![currentDocument canZoomOut]) {
         return NO;
      }
   }

   if ([[anItem title] isEqualToString:NSLocalizedString(@"ZoomOverlapIn", nil)]) {
      if(!currentDocument || ![currentDocument canZoomOverlapIn]) {
         return NO;
      }
   }

   if ([[anItem title] isEqualToString:NSLocalizedString(@"ZoomOverlapOut", nil)]) {
      if(!currentDocument || ![currentDocument canZoomOverlapOut]) {
         return NO;
      }
   }
   
   if ([[anItem title] isEqualToString:NSLocalizedString(@"MatrixView", nil)]) {
      if(!currentDocument || [currentDocument displayMode] == SSMatrixDisplayMode) {
         return NO;
      }
   }

   if ([[anItem title] isEqualToString:NSLocalizedString(@"OverlapView", nil)]) {
      if(!currentDocument || [currentDocument displayMode] == SSOverlapDisplayMode) {
         return NO;
      }
   }

   if ([[anItem title] isEqualToString:NSLocalizedString(@"DateRangeFilter", nil)]) {
      if(!currentDocument || [currentDocument displayMode] == SSOverlapDisplayMode) {
         return NO;
      }
   }

   if ([[anItem title] isEqualToString:NSLocalizedString(@"OverlapScaleAndRangeFilter", nil)]) {
      if(!currentDocument || [currentDocument displayMode] == SSMatrixDisplayMode) {
         return NO;
      }
   }
      
   return YES;
}




//***********************************eSellerate activation methods
- (void)installEngine
{
   /* Setup:
   *   fsRef, stores the location of the engine resource (used for FSOpenResourceFile())
   *   resFileRefNum, also used for the FSOpenResourceFile() function
   *   urlRef, the Cocoa representation of the resource file location (gets converted to fsRef)
   * Note:
   *	This is a somewhat complicated process because Cocoa doesn't handle the loading of resources well.
   *	Because of this, we have to call back into a non-Cocoa function (FSOpenResourceFile) to be able to
   *	load the resource while the app is running (from the flattened data file eSellerateEngine_DataFork.rsrc).
   */
   OSErr 		 			error = noErr;
   FSRef 		 			fsRef;
   SInt16 		 			resFileRefNum;
   NSBundle 	 			*myBundle = [NSBundle mainBundle];
   NSString	 			*path = [myBundle pathForResource:@"eSellerateEngine_DataFork" ofType:@"rsrc"];
   NSURL 		 			*urlRef = [[NSURL alloc] initFileURLWithPath:path];
   eSellerate_ErrorCode 	eSellErrorCode;

   if(CFURLGetFSRef((CFURLRef)urlRef, &fsRef))
   {
      if(FSOpenResourceFile(&fsRef, NULL, NULL, fsRdPerm, &resFileRefNum)==noErr)
      {
         eSellErrorCode = eSellerate_InstallEngine();
      }
   }

   CloseResFile(resFileRefNum);
   error = ResError();
   [urlRef release];
}

- (void)updateSN
{
   NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
   Str255 ESDSerialNumberPascal;
   eSellerate_ErrorCode validSN, validActivation;

   // We set the application to unregistered while we perform the validation of the serial number.
   [self setRegistered:NO];

   ESDSerialNumber = [defaults objectForKey:SSCatalystSerialNumberKey];

   if(![ESDSerialNumber isEqualToString:@""])
   {
      CFStringGetPascalString((CFStringRef)ESDSerialNumber, ESDSerialNumberPascal, 255, CFStringGetSystemEncoding());

      validSN = eSellerate_ValidateSerialNumber( ESDSerialNumberPascal, // Serial number (read from User Defaults)
                                                 nil, 				
                                                 nil,				
                                                 "\p04550");          
      if(validSN)
      {
         int activate;

         validActivation = eSellerate_ValidateActivation ("\pPUB738169100",  	// publisher ID code
                                                          "\pACT280075569", 		// activation ID code associated with serial number
                                                          ESDSerialNumberPascal);// Serial number

            // If there is no valid activation on this machine, try to activate this serial number

            if(validActivation)
            {
               activate = NSRunAlertPanel(@"Product Activation error.", @"Investigation Catalyst has not been activated on this machine. Would you like to activate now?", @"Yes", @"No", nil);

               if(activate == NSAlertDefaultReturn)
               {
                  NSString 	*resultString;


                  //		Since there was no valid activation for this machine, we try to activate the serial number.
                  //		We set the registration status based on the results returned from this function.
                 

                  validActivation = eSellerate_ActivateSerialNumber("\pPUB738169100",		// publisher ID code
                                                                    "\pACT280075569",		// activation ID code
                                                                    ESDSerialNumberPascal,// serial number
                                                                    TRUE);				// flag specifying whether to ask the user to connect
                  switch(validActivation)
                  {
                     case 0: // Product Activation was Successful.
                        resultString = @"Thank you for purchasing Investigation Catalyst";
                        NSRunAlertPanel(@"Product activation for Investigation Catalyst Succeeded.", resultString, @"Ok", nil, nil);
                        [self setRegistered:YES];
                        break;
                     case -25000: // Unknown Activation ID
                        resultString = @"Please contact the makers of Investigation Catalyst for further information.\n\n(Error = -25000)";
                        NSRunAlertPanel(@"Product activation for Investigation Catalyst failed.", resultString, @"Ok", nil, nil);
                        break;
                     case -25001: // Unknown Serial Number
                        resultString = @"Our server may not have finished processing your order yet. Please recheck your serial number and try again in a few minutes.\n\n(Error = -25001)";
                        NSRunAlertPanel(@"Product activation for Investigation Catalyst failed.", resultString, @"Ok", nil, nil);
                        break;
                     case -25002: // Publisher ID / Serial Number Mismatch
                        resultString = @"Please contact the makers of Investigation Catalyst for further information.\n\n(Error = -25002)";
                        NSRunAlertPanel(@"Product activation for Investigation Catalyst failed.", resultString, @"Ok", nil, nil);
                        break;
                     case -25003: // Blacklisted Serial Number
                        resultString = @"Please contact the makers of Investigation Catalyst for further information.\n\n(Error = -25003)";
                        NSRunAlertPanel(@"Product activation for Investigation Catalyst failed.", resultString, @"Ok", nil, nil);
                        break;
                     case -25004: // Invalid Order Status (ie Order Returned or Voided)
                        resultString = @"Please contact the makers of Investigation Catalyst for further information.\n\n(Error = -25004)";
                        NSRunAlertPanel(@"Product activation for Investigation Catalyst failed.", resultString, @"Ok", nil, nil);
                        break;
                     case -25005: // Activation limit met
                        resultString = @"Investigation Catalyst has already been registered on another computer. Please contact the makers of Investigation Catalyst for further information.\n\n(Error = -25005)";
                        NSRunAlertPanel(@"Product activation for Investigation Catalyst failed.", resultString, @"Ok", nil, nil);
                        break;
                     case -25009: // Non-unique Serial Number
                        resultString = @"Investigation Catalyst has already been registered on another computer. Please contact the makers of Investigation Catalyst for further information.\n\n(Error = -25009)";
                        NSRunAlertPanel(@"Product activation for Investigation Catalyst failed.", resultString, @"Ok", nil, nil);
                        break;
                     default:
                        resultString = @"An unkown error occured.  Please contact the makers of Investigation Catalyst for further information.";
                        NSRunAlertPanel(@"Product activation for Investigation Catalyst failed.", resultString, @"Ok", nil, nil);
                        break;
                  }
               }
            }
            else
               [self setRegistered:YES];
      }
   }
}

- (void)activate
{
   eSellerate_ErrorCode 	validActivation = eSellerate_FAILURE;
   Str255 			serialNumber = "\p";
   NSString 			*resultString;

   ESDSerialNumber = [[NSUserDefaults standardUserDefaults] objectForKey:SSCatalystSerialNumberKey];

   CFStringGetPascalString((CFStringRef)ESDSerialNumber, serialNumber, 255, CFStringGetSystemEncoding());


   validActivation = eSellerate_ActivateSerialNumber("\pPUB738169100",   /* publisher ID code (always needed) */
                                                           "\pACT280075569",  	/* activation ID code to associate with serial number (always needed) */
                                                           serialNumber,  	/* serial number (always needed) */
                                                           YES);

   switch(validActivation)
   {
      case 0: // Product Activation was Successful.
         resultString = @"Thank you for purchasing Investigation Catalyst";
         NSRunAlertPanel(@"Product activation for Investigation Catalyst Succeeded.", resultString, @"Ok", nil, nil);
         [self setRegistered:YES];
         break;
      case -25000: // Unknown Activation ID
         resultString = @"Please contact the makers of Investigation Catalyst for further information.\n\n(Error = -25000)";
         NSRunAlertPanel(@"Product activation for Investigation Catalyst failed.", resultString, @"Ok", nil, nil);
         break;
      case -25001: // Unknown Serial Number
         resultString = @"Our server may not have finished processing your order yet. Please recheck your serial number and try again in a few minutes.\n\n(Error = -25001)";
         NSRunAlertPanel(@"Product activation for Investigation Catalyst failed.", resultString, @"Ok", nil, nil);
         break;
      case -25002: // Publisher ID / Serial Number Mismatch
         resultString = @"Please contact the makers of Investigation Catalyst for further information.\n\n(Error = -25002)";
         NSRunAlertPanel(@"Product activation for Investigation Catalyst failed.", resultString, @"Ok", nil, nil);
         break;
      case -25003: // Blacklisted Serial Number
         resultString = @"Please contact the makers of Investigation Catalyst for further information.\n\n(Error = -25003)";
         NSRunAlertPanel(@"Product activation for Investigation Catalyst failed.", resultString, @"Ok", nil, nil);
         break;
      case -25004: // Invalid Order Status (ie Order Returned or Voided)
         resultString = @"Please contact the makers of Investigation Catalyst for further information.\n\n(Error = -25004)";
         NSRunAlertPanel(@"Product activation for Investigation Catalyst failed.", resultString, @"Ok", nil, nil);
         break;
      case -25005: // Activation limit met
         resultString = @"Investigation Catalyst has already been registered on another computer. Please contact the makers of Investigation Catalyst for further information.\n\n(Error = -25005)";
         NSRunAlertPanel(@"Product activation for Investigation Catalyst failed.", resultString, @"Ok", nil, nil);
         break;
      case -25009: // Non-unique Serial Number
         resultString = @"Investigation Catalyst has already been registered on another computer. Please contact the makers of Investigation Catalyst for further information.\n\n(Error = -25009)";
         NSRunAlertPanel(@"Product activation for Investigation Catalyst failed.", resultString, @"Ok", nil, nil);
         break;
      default:
         resultString = @"An unkown error occured.  Please contact the makers of Investigation Catalyst for further information.";
         NSRunAlertPanel(@"Product activation for Investigation Catalyst failed.", resultString, @"Ok", nil, nil);
         break;
   }
}

- (IBAction)menuPurchase:(id)sender
{
   /* Setup:
   *   resultData, stores the information returned from the engine
   *   serialArraySize, stores the size of the serial number array returned from eSellerate_IndexSerialNumberData();
   *   serialNumberArray, stores the serial numbers return from eSellerate_IndexSerialNumberData();
   */
   eSellerate_ResultData resultData = nil;
   eSellerate_ErrorCode error;
   eSellerate_ArraySize serialArraySize;
   eSellerate_OutputString serialNumberArray[1];
   NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

   /*
      *     Command the Software Delivery Wizard to perform the purchase specified.
      */

   error = eSellerate_Purchase ( "\pPUB738169100",                    //Publisher ID String
                                 "\pES9601641350",                     //eSeller RefNum
                                 nil,                //Preview Certificate
                                 "\phttp://www.investigationcatalyst.com", //URL String for contact in case of error
                                 nil, // Custom title of the opening page of the Wizard
                                 nil, // Custom first paragraph of the opening page of the Wizard
                                 0,   // Have the Engine open a window to display downloaded files (0 -> don't open window)
                                 nil, // Tracking ID code
                                 nil, // Affiliate ID code
                                 nil, // Coupon ID code
                                 "\pACT280075569", //Activation ID
                                 nil, // Extra information, for instance for custom serial numbers
                                 &resultData // Handle to memory to be allocated and filled by the Engine
                                 );
   /* Retrieve Serial Number Data:
      *   If purchase was a success, fill serialNumberArray with data using eSellerate_IndexSerialNumberData().
      *   We then convert it to a CFString to store it in User Defaults, and call updateSN: to validate it.
      */
   if(error == eSellerate_SUCCESS)
   {
      serialNumberArray[0] = "\p";

      serialArraySize = eSellerate_IndexSerialNumberData( resultData,        //Data to be referenced
                                                          nil,               //Product ID (not needed since we only have one serial number)
                                                          serialNumberArray, //Reference array to store serial numbers
                                                          nil,               //No name based key expected since we didn't specify this in the Sales Manager (under Serial Numbers)
                                                          1 );               //Size of reference array

      ESDSerialNumber = (NSString *)CFStringCreateWithPascalString(NULL, serialNumberArray[0], CFStringGetSystemEncoding());

      [defaults setObject:ESDSerialNumber forKey:SSCatalystSerialNumberKey];
      [self updateSN];
   }
   eSellerate_DeleteResultData(resultData);
}

- (BOOL)isValidSerialNumber:(NSString *)serial
{
   Str255 ESDSerialNumberPascal;
   eSellerate_ErrorCode validSN;

   CFStringGetPascalString((CFStringRef)serial, ESDSerialNumberPascal, 255, CFStringGetSystemEncoding());

   validSN = eSellerate_ValidateSerialNumber( ESDSerialNumberPascal,
                                              nil,
                                              nil,
                                              "\p04550");
   if(validSN) {
      return YES;
   } else {
      return NO;
   }
}

- (BOOL)isSerialNumberActivated:(NSString *)serial
{
   Str255 ESDSerialNumberPascal;
   eSellerate_ErrorCode validActivation;
   
   CFStringGetPascalString((CFStringRef)serial, ESDSerialNumberPascal, 255, CFStringGetSystemEncoding());

   validActivation = eSellerate_ValidateActivation ("\pPUB738169100",  	// publisher ID code
                                                    "\pACT280075569", 		// activation ID code associated with serial number
                                                    ESDSerialNumberPascal);// Serial number
   if(validActivation) {
      return YES;
   } else {
      return NO;
   }
}

//***********************************

- (void)dealloc
{
   [[NSNotificationCenter defaultCenter] removeObserver:self];
   [ESDSerialNumber release];
   [super dealloc];
}

@end
